package com.artfii.fluentsql.core;

import com.artfii.fluentsql.core.tools.Attr;

/**
 * Func : SQl 的 Function
 * 注意:如果使用在子查询里则要指定拼写为 Spell.UNDERLINE
 * @author: leeton on 2019/6/18.
 */
public class Qf<T> {
    public String sql = "";
    private Attr.Property<T, ?> field;
    private Object defaultVal;
    private String as;
    private FUNC func;
    private Spell spell;
    private LambdaQuery condition; //表达式

    public static <T> Qf ifnull(Attr.Property<T, ?> field) {
        return new Qf().build(field, 0, null, FUNC.IFNULL, Spell.CAMEL);
    }

    public static <T> Qf ifnull(Attr.Property<T, ?> field, String as) {
        return new Qf().build(field, 0, as, FUNC.IFNULL, null);
    }

    public static <T> Qf ifnull(Attr.Property<T, ?> field, Spell spell) {
        return new Qf().build(field, 0, null, FUNC.IFNULL, spell);
    }

    public static <T> Qf ifnull(Attr.Property<T, ?> field, Object defVal, Spell spell) {
        return new Qf().build(field, defVal, null, FUNC.IFNULL, spell);
    }

    public static <T> Qf ifnull(Attr.Property<T, ?> field, Object defaultVal, String as) {
        return new Qf().build(field, defaultVal, as, FUNC.IFNULL, null);
    }

    public static <T> Qf sum(Attr.Property<T, ?> field) {
        return new Qf().build(field, 0, null, FUNC.SUM, Spell.CAMEL);
    }

    public static <T> Qf sum(Attr.Property<T, ?> field, String as) {
        return new Qf().build(field, 0, as, FUNC.SUM, null);
    }

    public static <T> Qf sum(Attr.Property<T, ?> field, Spell spell) {
        return new Qf().build(field, 0, null, FUNC.SUM, spell);
    }

    public static <T> Qf sumIF(LambdaQuery condition, Attr.Property<T, ?> sumfield) {
        return sumIF(condition, sumfield, 0, null);
    }

    public static <T> Qf sumIF(LambdaQuery condition, Attr.Property<T, ?> sumfield, String as) {
        return sumIF(condition, sumfield, 0, as);
    }
    public static <T> Qf sumIF(LambdaQuery condition, Attr.Property<T, ?> sumfield, Object defaultVal) {
        return sumIF(condition, sumfield, defaultVal, null);
    }
    public static <T> Qf sumIF(LambdaQuery condition, Attr.Property<T, ?> sumfield, Object defaultVal,String as) {
        return new Qf().build(condition, sumfield, defaultVal, as, Spell.CAMEL);
    }

    public static <T> Qf max(Attr.Property<T, ?> field) {
        return new Qf().build(field, 0, null, FUNC.MAX, Spell.CAMEL);
    }

    public static <T> Qf max(Attr.Property<T, ?> field, String as) {
        return new Qf().build(field, 0, as, FUNC.MAX, null);
    }

    public static <T> Qf max(Attr.Property<T, ?> field, Spell spell) {
        return new Qf().build(field, 0, null, FUNC.MAX, spell);
    }

    public static <T> Qf min(Attr.Property<T, ?> field) {
        return new Qf().build(field, 0, null, FUNC.MIN, Spell.CAMEL);
    }

    public static <T> Qf min(Attr.Property<T, ?> field, String as) {
        return new Qf().build(field, 0, as, FUNC.MIN, null);
    }

    public static <T> Qf min(Attr.Property<T, ?> field, Spell spell) {
        return new Qf().build(field, null, null, FUNC.MIN, spell);
    }

    public static <T> Qf countAs(Attr.Property<T, ?> field, String as) {
        return new Qf().build(field, null, as, FUNC.COUNT, null);
    }

    private Qf build(Attr.Property<T, ?> field, Object defaultVal, String as, FUNC func, Spell spell) {
        this.field = field;
        this.defaultVal = defaultVal;
        this.as = as;
        this.func = func;
        this.sql = sql();
        return this;
    }

    private Qf build(Qf qf, Object defaultVal, String as, FUNC func, Spell spell) {
        this.defaultVal = defaultVal;
        this.as = as;
        this.func = func;
        this.sql = sql();
        return qf;
    }

    private Qf build(LambdaQuery condition, Attr.Property<T, ?> sumfield, Object defaultVal, String as, Spell spell) {
        this.defaultVal = defaultVal;
        this.as = as;
        this.func = FUNC.SUMIF;
        this.field=sumfield;
        this.condition = condition;
        this.sql = buildSumIFSql();
        return this;
    }

    private <T> String sql() {
        StringBuffer funcSql = new StringBuffer(32);
        if (FUNC.COUNT == func) {
            return funcSql.append(" COUNT(1) AS ").append(as).toString();
        }
        //
        Attr attr = Attr.parse(field);
        String underline_column = attr.getColumn();
        String camel_column = attr.getName();
        String table = attr.getTableName();
        as = Spell.to(as, spell, underline_column, camel_column);
        if (null != defaultVal) {
            funcSql.append("IFNULL(");
            funcSql.append(func.name()).append("(").append(table).append(".").append(underline_column).append(")");
            funcSql.append(",").append(defaultVal);
            funcSql.append(")");
        } else {
            funcSql.append(func.name()).append("(").append(table).append(".").append(underline_column);
            funcSql.append(")");
        }
        if (null != as && !"".equals(as)) {
            funcSql.append(" AS ").append(as);
        }
        return funcSql.toString();
    }

    private <T> String buildSumIFSql() {
        StringBuffer funcSql = new StringBuffer(64);
        Attr attr = Attr.parse(field);
        String underline_column = attr.getColumn();
        String camel_column = attr.getName();
        String table = attr.getTableName();
        as = Spell.to(as, spell, underline_column, camel_column);
        funcSql.append("SUM IF(")
                .append(condition.buildCondition()).append(",") //构建表达式
                .append(table).append(".").append(underline_column) //SUM的目标字段
                .append(",").append(defaultVal)
                .append(")");
        if (null != as && !"".equals(as)) {
            funcSql.append(" AS ").append(as);
        }
        return funcSql.toString();
    }

    public enum FUNC {
        IFNULL, SUM, SUMIF, MAX, MIN, COUNT
    }



}
